// TorrentSearchService.java
package com.example.demo.service;

import com.example.demo.model.Torrent;
import com.example.demo.model.es.TorrentES;
import com.example.demo.repository.es.TorrentESRepository;

import co.elastic.clients.elasticsearch._types.query_dsl.Operator;
import co.elastic.clients.elasticsearch._types.query_dsl.*;
// 确保有以下导入
import org.springframework.data.domain.*;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;

import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class TorrentSearchService {
    @Autowired
    private TorrentESRepository torrentESRepository;

    @Autowired
    private LLMService llmService;

    @Autowired
    private ElasticsearchOperations elasticsearchOperations;

    // 基础搜索（带缓存）
    //@Cacheable(value = "searchResults", key = "#query + ':' + #pageable.pageNumber + ':' + #pageable.pageSize")
    public Page<TorrentES> search(String query, Pageable pageable) {
        try {
            return torrentESRepository.findByFileNameContainingOrSummaryContaining(query, query, pageable);
        } catch (Exception e) {
            // 打印底层异常信息
            Throwable cause = e.getCause();
            while (cause != null) {
                System.err.println("Caused by: " + cause.getMessage());
                cause = cause.getCause();
            }
            throw e;
        }
    }

    // 高级搜索（带缓存）
    @Cacheable(value = "advancedSearchResults", key = "#title + ':' + #category + ':' + #keywords + ':' + #pageable.pageNumber + ':' + #pageable.pageSize")
    public Page<TorrentES> advancedSearch(String title, String category, List<String> keywords, Pageable pageable) {
        String query = buildQuery(title, category, keywords);
        return torrentESRepository.advancedSearch(query, pageable);
    }

    // 基于自然语言描述的搜索
    //@Cacheable(value = "naturalLanguageSearchResults", key = "#description + ':' + #pageable.pageNumber + ':' + #pageable.pageSize")
//    public Page<TorrentES> searchByDescription(String description, Pageable pageable) throws IOException, InterruptedException {
//        List<String> keywords = llmService.extractKeywords(description);
//
//        // 对关键词进行转义，防止特殊字符问题
//        List<String> escapedKeywords = keywords.stream()
//                .map(keyword -> keyword.replaceAll("([+\\-=&|><!(){}\\[\\]^\"~*?:\\\\/])", "\\\\$1"))
//                .collect(Collectors.toList());
//
//        // 构造更安全的查询
//        String processedQuery = escapedKeywords.stream()
//                .map(keyword -> "(" + keyword + ")")
//                .collect(Collectors.joining(" OR "));
//
//        System.out.println("Final query: " + processedQuery);
//
//        try {
//            return torrentESRepository.advancedSearch(processedQuery, pageable);
//        } catch (Exception e) {
//            // 打印更详细的错误信息
//            e.printStackTrace();
//            throw new RuntimeException("Search failed: " + e.getMessage(), e);
//        }
//    }
//    public SearchPage<TorrentES> searchByDescription(String description, Pageable pageable)
//            throws IOException, InterruptedException {
//
//        List<String> keywords = llmService.extractKeywords(description);
//        try {
//            // 构建查询
////        Query query = QueryBuilders.queryString()
////                .query(String.join(" OR ", keywords))
////                .fields("fileName", "summary")
////                .defaultOperator(Operator.Or)
////                .analyzeWildcard(true)
////                .build()
////                ._toQuery();
//            Query query = QueryBuilders.matchAll().build()._toQuery();
//            NativeQuery searchQuery = NativeQuery.builder()
//                    .withQuery(query)
//                    .withPageable(pageable)
//                    .build();
//
//            // 1. 执行搜索获取 SearchHits
//            SearchHits<TorrentES> searchHits = elasticsearchOperations.search(searchQuery,
//                    TorrentES.class,
//                    IndexCoordinates.of("torrents"));
//
//            // 2. 将 SearchHits 转换为 SearchPage
//
//            // 3. SearchPage 可以直接作为 Page 返回
//            return SearchHitSupport.searchPageFor(searchHits, pageable);
//        } catch (Exception e) {
//            // 打印更详细的错误信息
//            e.printStackTrace();
//            throw new RuntimeException("Search failed: " + e.getMessage(), e);
//        }
//    }
    private static final String INDEX_NAME = "torrents";  // 定义常量

    // 基于自然语言描述的搜索
    public Page<TorrentES> searchByDescription(String description, Pageable pageable)
            throws IOException, InterruptedException {

        // 1. 提取关键词（最多8个）
        List<String> keywords = llmService.extractKeywords(description);
        System.out.println("提取的关键词: " + keywords);
        if (keywords == null || keywords.isEmpty()) {
            return Page.empty();
        }
        if (keywords.size() > 8) {
            keywords = keywords.subList(0, 8);
        }
        System.out.println("提取的关键词: " + keywords);

        // 2. 为每个关键词执行搜索
        Set<TorrentES> uniqueResults = new HashSet<>();
        for (String keyword : keywords) {
            Page<TorrentES> page = torrentESRepository.findByFileNameContainingOrSummaryContaining(
                    keyword, keyword, Pageable.unpaged()
            );
            uniqueResults.addAll(page.getContent());
        }

        // 3. 将结果转换为列表并排序
        List<TorrentES> mergedResults = new ArrayList<>(uniqueResults);
        mergedResults.sort(Comparator.comparing(TorrentES::getCreateTime).reversed());

        // 4. 手动分页处理
        int pageSize = pageable.getPageSize();
        int currentPage = pageable.getPageNumber();
        int start = currentPage * pageSize;
        int totalItems = mergedResults.size();

        // 计算分页边界
        if (start >= totalItems) {
            return new PageImpl<>(Collections.emptyList(), pageable, totalItems);
        }

        int end = Math.min(start + pageSize, totalItems);
        List<TorrentES> paginatedList = mergedResults.subList(start, end);

        // 5. 构建标准Page对象
        return new PageImpl<>(
                paginatedList,
                PageRequest.of(currentPage, pageSize, Sort.by(Sort.Order.desc("createTime"))),
                totalItems
        );
    }

    private Query buildMultiMatchQuery(List<String> keywords) {
        // 将关键词列表转换为空格分隔的字符串
        String queryString = String.join(" ", keywords);

        return QueryBuilders.multiMatch()
                .query(queryString)
                .fields("fileName^3", "summary^2", "description") // 设置字段权重
                .type(TextQueryType.MostFields) // 使用MostFields类型
                .operator(Operator.Or) // 使用OR逻辑
                .build()
                ._toQuery();
    }
    // 更新ES索引
    public void indexTorrent(Torrent torrent) {
        TorrentES torrentES = convertToES(torrent);
        torrentESRepository.save(torrentES);
    }

    // 删除ES索引
    public void deleteTorrent(Long id) {
        torrentESRepository.deleteById(id);
    }

    private TorrentES convertToES(Torrent torrent) {
        TorrentES torrentES = new TorrentES();
        torrentES.setId(torrent.getId());
        torrentES.setFileName(torrent.getFileName());
        torrentES.setFileSize(torrent.getFileSize());
        torrentES.setInfoHash(torrent.getInfoHash());
        torrentES.setUploaderId(torrent.getUploaderId());
        torrentES.setCreateTime(torrent.getCreateTime());
        torrentES.setSeeders(torrent.getSeeders());
        torrentES.setLeechers(torrent.getLeechers());
        torrentES.setSummary(generateSummary(torrent));
        torrentES.setScore(torrent.getScore());
        torrentES.setPromotionFree(torrent.isPromotionFree());
        torrentES.setOriginalScore(torrent.getOriginalScore());
        torrentES.setPromotionStartTime(torrent.getPromotionStartTime());
        torrentES.setPromotionEndTime(torrent.getPromotionEndTime());
        return torrentES;
    }

    private String generateSummary(Torrent torrent) {
        List<String> keywords = llmService.extractKeywords(torrent.getName());

        String result = keywords.stream()
                .limit(3) // 限制最多取3个元素
                .collect(Collectors.joining(", ")); // 使用", "作为分隔符连

        return String.format("资源名称: %s, 上传者ID: %d, 种子数: %d, 描述: %s 用户自定名称： %s ，标签： %s",
                torrent.getFileName(),
                torrent.getUploaderId(),
                torrent.getSeeders(),
                torrent.getDescription(),
                torrent.getName(),
                result
                );
    }

    private String buildQuery(String title, String category, List<String> keywords) {
        StringBuilder sb = new StringBuilder();
        if (title != null) sb.append(title).append(" ");
        if (category != null) sb.append(category).append(" ");
        if (keywords != null) keywords.forEach(k -> sb.append(k).append(" "));
        return sb.toString().trim();
    }
}